using System;

using System.Text;
using System.Text.RegularExpressions;

using System.Collections;
using System.Collections.Specialized;

namespace Antix.Mail
{
    /// <summary>
    /// Base object for mail messages
    /// 
    /// http://www.faqs.org/rfcs/rfc2822.html
    /// </summary>
    public class Message 
    {
        #region Constructors etc.

        /// <summary>
        /// Create a message
        /// </summary>
        public Message()
            : this("")
        {
            _RequiresDownload = false;
        }

        /// <summary>
        /// Create a message
        /// </summary>
        /// <param name="id">Message id</param>
        internal Message(string id)
        {
            _RequiresDownload = true;

            _To = new ContactCollection();
            _CC = new ContactCollection();
            _BCC = new ContactCollection();
        }

        #endregion

        #region Properties

        #region Data

        /// <summary>
        /// The raw data for this message
        /// </summary>
        protected string _DataRaw;

        #endregion

        #region Headers

        private MessageContentHeaders _Headers;

        /// <summary>
        /// Message headers
        /// </summary>
        public MessageContentHeaders Headers
        {
            get { return _Headers; }
        }

        #endregion

        #region Id

        /// <summary>
        /// Content Id
        /// </summary>
        public string Id
        {
            get { return Headers[MessageContentHeaderType.MessageId].TrimStart('<').TrimEnd('>'); }
        }

        #endregion

        #region RequiresDownload

        private bool _RequiresDownload;

        /// <summary>
        /// This message requires downloading
        /// </summary>
        internal bool RequiresDownload
        {
            get { return _RequiresDownload; }
            set { _RequiresDownload = value; }
        }

        #endregion

        #region Subject

        /// <summary>
        /// Subject of the message
        /// </summary>
        public string Subject
        {
            get { return Headers[Subject]; }
            set { Headers[Subject] = value; }
        }

        #endregion

        #region From

        private Contact _From;

        /// <summary>
        /// From contact for the message
        /// </summary>
        public Contact From
        {
            get { return _From; }
            set { _From = value; }
        }

        #endregion

        #region To

        private ContactCollection _To;

        /// <summary>
        /// Recipients the message
        /// </summary>
        public ContactCollection To
        {
            get { return _To; }
        }

        #endregion

        #region CC

        private ContactCollection _CC;

        /// <summary>
        /// CC contacts for the message
        /// </summary>
        public ContactCollection CC
        {
            get { return _CC; }
        }

        #endregion

        #region BCC

        private ContactCollection _BCC;

        /// <summary>
        /// CC contacts for the message
        /// </summary>
        public ContactCollection BCC
        {
            get { return _CC; }
        }

        #endregion

        #region SentDate

        /// <summary>
        /// Date the message was sent
        /// </summary>
        public DateTime SentDate
        {
            get { return DateTimeFunctions.Parse(Headers["date"], DateTime.MinValue); }
        }

        #endregion

        #region Text

        private MessageContent _TextContent = null;

        /// <summary>
        /// Message Text
        /// </summary>
        public string Text
        {
            get
            {
                if (_TextContent == null) { _TextContent = new MessageContent(); }
                return _TextContent.Data;
            }
            set { _TextContent.Data = value; }
        }

        #endregion

        #region Html

        private MessageContent _HtmlContent = null;

        /// <summary>
        /// Message Html
        /// </summary>
        public string Html
        {
            get
            {
                if (_HtmlContent == null) { _HtmlContent = new MessageContent(); }
                return _HtmlContent.Data;
            }
            set { _HtmlContent.Data = value; }
        }

        #endregion

        #region MailAttachments

        /// <summary>
        /// Attachments
        /// </summary>
        protected AttachmentCollection _Attachments;

        /// <summary>
        /// Attachments
        /// </summary>
        public AttachmentCollection Attachments
        {
            get
            {
                if (_Attachments == null)
                {
                    _Attachments = new AttachmentCollection();
                }
                return _Attachments;
            }
        }

        #endregion

        #endregion

        #region Methods

        #region Save

        /// <summary>
        /// Save to disk
        /// </summary>
        public void Save(string fileName)
        {
            IOFunctions.CreateTextFile(fileName, _DataRaw);
        }

        #endregion

        /// <summary>
        /// Set the data fo this message
        /// </summary>
        public void ParseData(string data)
        {
            // store the raw data
            _DataRaw = data;

            // Parse the headers
            _Headers = new MessageContentHeaders(TextFunctions.Head(ref data, "\r\n\r\n"));

            if (this.Headers.Boundary == null)
            {
                // simple text e-mail
                _TextContent.DataRaw = data;
            }else{
                // parse the bounded data
                ParseBoundries(data, this.Headers.Boundary);
            }
        }

        private void ParseBoundries(string data, string boundary)
        {
            // ignore first section
            TextFunctions.Head(ref data, boundary);
            while (data.Length > 0)
            {
                string contentData = TextFunctions.Head(ref data, "--" + boundary);
                MessageContentHeaders contentHeaders
                    = new MessageContentHeaders(TextFunctions.Head(ref contentData, "\r\n\r\n"));

                if (contentHeaders.Boundary == null)
                {
                    if (contentHeaders.Disposition == MessageContentDispositionType.Attachment)
                    {
                        this.Attachments.Add(contentHeaders, contentData);
                    }
                    else
                    {
                        switch (contentHeaders.ContentType)
                        {
                            case MessageContentType.TextPlain:
                                _TextContent = new MessageContent(contentHeaders, contentData);

                                break;
                            case MessageContentType.TextHtml:
                                _HtmlContent = new MessageContent(contentHeaders, contentData);

                                break;
                        }
                    }
                }
                else
                {
                    ParseBoundries(contentData, contentHeaders.Boundary);
                }
            }
        }

        #endregion
    }
}